/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.lvyh.lightframe.sharding.admin.service;

import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.lvyh.lightframe.sharding.admin.bean.ShardingDbGroupBean;
import com.lvyh.lightframe.sharding.admin.bean.ShardingDbTableBean;
import com.lvyh.lightframe.sharding.admin.bean.ShardingGroupBean;
import com.lvyh.lightframe.sharding.admin.dao.entity.ShardingDbGroup;
import com.lvyh.lightframe.sharding.admin.dao.entity.ShardingDbGroupExample;
import com.lvyh.lightframe.sharding.admin.dao.entity.ShardingDbTable;
import com.lvyh.lightframe.sharding.admin.dao.entity.ShardingDbTableExample;
import com.lvyh.lightframe.sharding.admin.dao.entity.ShardingGroup;
import com.lvyh.lightframe.sharding.admin.dao.entity.ShardingGroupExample;
import com.lvyh.lightframe.sharding.admin.dao.mapper.ShardingDbGroupMapper;
import com.lvyh.lightframe.sharding.admin.dao.mapper.ShardingDbTableMapper;
import com.lvyh.lightframe.sharding.admin.dao.mapper.ShardingGroupMapper;
import com.lvyh.lightframe.sharding.client.pagination.DefaultPageResult;
import com.lvyh.lightframe.sharding.client.pagination.PageParam;
import com.lvyh.lightframe.sharding.client.util.BeanUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 * @author lvyh 2021/08/01.
 */
@Service
public class ShardingMainDataService {

    private final static Logger logger = LoggerFactory.getLogger(ShardingMainDataService.class);
    @Autowired
    private ShardingDbGroupMapper shardingDbGroupMapper;
    @Autowired
    private ShardingDbTableMapper shardingDbTableMapper;
    @Autowired
    private ShardingGroupMapper shardingGroupMapper;


    public boolean deleteShardingGroup(Integer id) throws Exception {
        if (id == null) {
            return false;
        }
        try {
            int updateNum = shardingGroupMapper.deleteByPrimaryKey(id);
            return updateNum == 1;
        } catch (Exception exp) {
            logger.error(exp.getMessage(), exp);
            throw exp;
        }
    }

    public List<ShardingGroupBean> selectShardingGroup(ShardingGroupBean condition) throws Exception {
        List<ShardingGroupBean> list = new ArrayList<ShardingGroupBean>();
        try {
            ShardingGroupExample example = new ShardingGroupExample();
            ShardingGroupExample.Criteria criteria = example.createCriteria();
            if (condition.getId() != null) {
                criteria.andIdEqualTo(condition.getId());
            }


            List<ShardingGroup> queryDataItems = shardingGroupMapper.selectByExample(example);
            if (CollectionUtils.isEmpty(queryDataItems)) {
                return list;
            }

            for (ShardingGroup shardingGroup : queryDataItems) {
                list.add(BeanUtil.toBean(ShardingGroupBean.class, BeanUtil.toMap(shardingGroup)));
            }

        } catch (Exception exp) {
            logger.error(exp.getMessage(), exp);
            throw exp;
        }
        return list;
    }

    public DefaultPageResult<ShardingGroupBean> selectShardingGroupByCondition(ShardingGroupBean condition, PageParam pageParam) throws Exception {
        if (pageParam == null) {
            throw new Exception("pageParam must need");
        }

        Page<ShardingGroup> page = PageHelper.startPage(pageParam.getPageNo(), pageParam.getPageSize());
        if (!StringUtils.isEmpty(pageParam.getOrderColumns())) {
            page.setOrderBy(pageParam.getOrderColumns());
        }

        try {
            ShardingGroupExample example = new ShardingGroupExample();
            if (condition != null) {
                ShardingGroupExample.Criteria criteria = example.createCriteria();
                if (condition.getId() != null) {
                    criteria.andIdEqualTo(condition.getId());
                }

            }

            List<ShardingGroup> queryDataItems = shardingGroupMapper.selectByExample(example);
            DefaultPageResult<ShardingGroupBean> result = new DefaultPageResult<>();
            if (queryDataItems == null || queryDataItems.size() == 0) {
                return result;
            }

            List<ShardingGroupBean> list = new ArrayList<ShardingGroupBean>();
            for (ShardingGroup shardingGroup : queryDataItems) {
                list.add(BeanUtil.toBean(ShardingGroupBean.class, BeanUtil.toMap(shardingGroup)));
            }

            result.setResultList(list);
            result.setPageSize(page.getPageSize());
            result.setPageNo(page.getPageNum());
            result.setTotalCount((int) page.getTotal());
            result.setTotalPage(page.getPages());
            return result;
        } catch (Exception exp) {
            logger.error(exp.getMessage(), exp);
            throw exp;
        }
    }

    public int countShardingGroupByCondition(ShardingGroupBean condition) throws Exception {
        try {
            ShardingGroupExample example = new ShardingGroupExample();
            if (condition != null) {
                ShardingGroupExample.Criteria criteria = example.createCriteria();
                if (condition.getId() != null) {
                    criteria.andIdEqualTo(condition.getId());
                }


            }

            return shardingGroupMapper.countByExample(example);
        } catch (Exception exp) {
            logger.error(exp.getMessage(), exp);
            throw exp;
        }
    }

    @Transactional(rollbackFor = {RuntimeException.class})
    public boolean updateShardingGroup(ShardingGroupBean shardingGroupBean) throws Exception {
        if (shardingGroupBean == null || shardingGroupBean.getId() <= 0) {
            return false;
        }
        try {
            shardingGroupBean.setUpdateTime(new Date());
            ShardingGroup updateBean = BeanUtil.toBean(ShardingGroup.class, BeanUtil.toMap(shardingGroupBean));
            int updateNum = shardingGroupMapper.updateByPrimaryKeySelective(updateBean);
            return updateNum == 1;
        } catch (Exception exp) {
            logger.error(exp.getMessage(), exp);
            throw exp;
        }
    }

    public ShardingGroupBean selectShardingGroupById(Integer id) throws Exception {
        if (id <= 0) {
            return null;
        }
        try {
            ShardingGroup shardingGroup = shardingGroupMapper.selectByPrimaryKey(id);
            if (shardingGroup == null) {
                logger.warn("not found data, tid:{}", id);
                return null;
            }
            return BeanUtil.toBean(ShardingGroupBean.class, BeanUtil.toMap(shardingGroup));
        } catch (Exception exp) {
            logger.error(exp.getMessage(), exp);
            throw exp;
        }
    }

    public Integer saveShardingGroup(ShardingGroupBean shardingGroupBean) throws Exception {
        if (shardingGroupBean == null) {
            return -1;
        }
        try {
            shardingGroupBean.setCreateTime(new Date());
            shardingGroupBean.setUpdateTime(new Date());
            ShardingGroup insertBean = BeanUtil.toBean(ShardingGroup.class, BeanUtil.toMap(shardingGroupBean));
            shardingGroupMapper.insertSelective(insertBean);
            return insertBean.getId();
        } catch (Exception exp) {
            logger.error(exp.getMessage(), exp);
            throw exp;
        }
    }

    public boolean deleteShardingDbTable(Integer id) throws Exception {
        if (id == null) {
            return false;
        }
        try {
            int updateNum = shardingDbTableMapper.deleteByPrimaryKey(id);
            return updateNum == 1;
        } catch (Exception exp) {
            logger.error(exp.getMessage(), exp);
            throw exp;
        }
    }

    public List<ShardingDbTableBean> selectShardingDbTable(ShardingDbTableBean condition) throws Exception {
        List<ShardingDbTableBean> list = new ArrayList<ShardingDbTableBean>();
        try {
            ShardingDbTableExample example = new ShardingDbTableExample();
            ShardingDbTableExample.Criteria criteria = example.createCriteria();
            if (condition.getId() != null) {
                criteria.andIdEqualTo(condition.getId());
            }

            if (condition.getDbId() != null) {
                criteria.andDbIdEqualTo(condition.getDbId());
            }

            List<ShardingDbTable> queryDataItems = shardingDbTableMapper.selectByExample(example);
            if (CollectionUtils.isEmpty(queryDataItems)) {
                return list;
            }

            for (ShardingDbTable shardingDbTable : queryDataItems) {
                list.add(BeanUtil.toBean(ShardingDbTableBean.class, BeanUtil.toMap(shardingDbTable)));
            }

        } catch (Exception exp) {
            logger.error(exp.getMessage(), exp);
            throw exp;
        }
        return list;
    }

    public DefaultPageResult<ShardingDbTableBean> selectShardingDbTableByCondition(ShardingDbTableBean condition, PageParam pageParam) throws Exception {
        if (pageParam == null) {
            throw new Exception("pageParam must need");
        }

        Page page = PageHelper.startPage(pageParam.getPageNo(), pageParam.getPageSize());
        if (!StringUtils.isEmpty(pageParam.getOrderColumns())) {
            page.setOrderBy(pageParam.getOrderColumns());
        }

        try {
            ShardingDbTableExample example = new ShardingDbTableExample();
            if (condition != null) {
                ShardingDbTableExample.Criteria criteria = example.createCriteria();
                if (condition.getId() != null) {
                    criteria.andIdEqualTo(condition.getId());
                }

            }

            List<ShardingDbTable> queryDataItems = shardingDbTableMapper.selectByExample(example);
            DefaultPageResult<ShardingDbTableBean> result = new DefaultPageResult<>();
            if (queryDataItems == null || queryDataItems.size() == 0) {
                return result;
            }

            List<ShardingDbTableBean> list = new ArrayList<ShardingDbTableBean>();
            for (ShardingDbTable shardingDbTable : queryDataItems) {
                list.add(BeanUtil.toBean(ShardingDbTableBean.class, BeanUtil.toMap(shardingDbTable)));
            }

            result.setResultList(list);
            result.setPageSize(page.getPageSize());
            result.setPageNo(page.getPageNum());
            result.setTotalCount((int) page.getTotal());
            result.setTotalPage(page.getPages());
            return result;
        } catch (Exception exp) {
            logger.error(exp.getMessage(), exp);
            throw exp;
        }
    }

    public int countShardingDbTableByCondition(ShardingDbTableBean condition) throws Exception {
        try {
            ShardingDbTableExample example = new ShardingDbTableExample();
            if (condition != null) {
                ShardingDbTableExample.Criteria criteria = example.createCriteria();
                if (condition.getId() != null) {
                    criteria.andIdEqualTo(condition.getId());
                }


            }

            return shardingDbTableMapper.countByExample(example);
        } catch (Exception exp) {
            logger.error(exp.getMessage(), exp);
            throw exp;
        }
    }

    @Transactional(rollbackFor = {RuntimeException.class})
    public boolean updateShardingDbTable(ShardingDbTableBean shardingDbTableBean) throws Exception {
        if (shardingDbTableBean == null || shardingDbTableBean.getId() <= 0) {
            return false;
        }
        try {
            shardingDbTableBean.setUpdateTime(new Date());
            ShardingDbTable updateBean = BeanUtil.toBean(ShardingDbTable.class, BeanUtil.toMap(shardingDbTableBean));
            int updateNum = shardingDbTableMapper.updateByPrimaryKeySelective(updateBean);
            return updateNum == 1;
        } catch (Exception exp) {
            logger.error(exp.getMessage(), exp);
            throw exp;
        }
    }

    public ShardingDbTableBean selectShardingDbTableById(Integer id) throws Exception {
        if (id <= 0) {
            return null;
        }
        try {
            ShardingDbTable shardingDbTable = shardingDbTableMapper.selectByPrimaryKey(id);
            if (shardingDbTable == null) {
                logger.warn("not found data, tid:{}", id);
                return null;
            }
            return BeanUtil.toBean(ShardingDbTableBean.class, BeanUtil.toMap(shardingDbTable));
        } catch (Exception exp) {
            logger.error(exp.getMessage(), exp);
            throw exp;
        }
    }

    public Integer saveShardingDbTable(ShardingDbTableBean shardingDbTableBean) throws Exception {
        if (shardingDbTableBean == null) {
            return -1;
        }
        try {
            shardingDbTableBean.setCreateTime(new Date());
            shardingDbTableBean.setUpdateTime(new Date());
            ShardingDbTable insertBean = BeanUtil.toBean(ShardingDbTable.class, BeanUtil.toMap(shardingDbTableBean));
            shardingDbTableMapper.insertSelective(insertBean);
            return insertBean.getId();
        } catch (Exception exp) {
            logger.error(exp.getMessage(), exp);
            throw exp;
        }
    }

    public boolean deleteShardingDbGroup(Integer id) throws Exception {
        if (id == null) {
            return false;
        }
        try {
            int updateNum = shardingDbGroupMapper.deleteByPrimaryKey(id);
            return updateNum == 1;
        } catch (Exception exp) {
            logger.error(exp.getMessage(), exp);
            throw exp;
        }
    }

    public List<ShardingDbGroupBean> selectShardingDbGroup(ShardingDbGroupBean condition) throws Exception {
        List<ShardingDbGroupBean> list = new ArrayList<ShardingDbGroupBean>();
        try {
            ShardingDbGroupExample example = new ShardingDbGroupExample();
            ShardingDbGroupExample.Criteria criteria = example.createCriteria();
            if (condition.getId() != null) {
                criteria.andIdEqualTo(condition.getId());
            }
            if (condition.getGroupId() != null) {
                criteria.andGroupIdEqualTo(condition.getGroupId());
            }

            List<ShardingDbGroup> queryDataItems = shardingDbGroupMapper.selectByExample(example);
            if (CollectionUtils.isEmpty(queryDataItems)) {
                return list;
            }

            for (ShardingDbGroup shardingDbGroup : queryDataItems) {
                list.add(BeanUtil.toBean(ShardingDbGroupBean.class, BeanUtil.toMap(shardingDbGroup)));
            }

        } catch (Exception exp) {
            logger.error(exp.getMessage(), exp);
            throw exp;
        }
        return list;
    }

    public DefaultPageResult<ShardingDbGroupBean> selectShardingDbGroupByCondition(ShardingDbGroupBean condition, PageParam pageParam) throws Exception {
        if (pageParam == null) {
            throw new Exception("pageParam must need");
        }
        Page page = PageHelper.startPage(pageParam.getPageNo(), pageParam.getPageSize());
        if (!StringUtils.isEmpty(pageParam.getOrderColumns())) {
            page.setOrderBy(pageParam.getOrderColumns());
        }

        try {
            ShardingDbGroupExample example = new ShardingDbGroupExample();
            if (condition != null) {
                ShardingDbGroupExample.Criteria criteria = example.createCriteria();
                if (condition.getId() != null) {
                    criteria.andIdEqualTo(condition.getId());
                }

            }

            List<ShardingDbGroup> queryDataItems = shardingDbGroupMapper.selectByExample(example);
            DefaultPageResult<ShardingDbGroupBean> result = new DefaultPageResult<>();
            if (queryDataItems == null || queryDataItems.size() == 0) {
                return result;
            }

            List<ShardingDbGroupBean> list = new ArrayList<ShardingDbGroupBean>();
            for (ShardingDbGroup shardingDbGroup : queryDataItems) {
                list.add(BeanUtil.toBean(ShardingDbGroupBean.class, BeanUtil.toMap(shardingDbGroup)));
            }

            result.setResultList(list);
            result.setPageSize(page.getPageSize());
            result.setPageNo(page.getPageNum());
            result.setTotalCount((int) page.getTotal());
            result.setTotalPage(page.getPages());
            return result;
        } catch (Exception exp) {
            logger.error(exp.getMessage(), exp);
            throw exp;
        }
    }

    public int countShardingDbGroupByCondition(ShardingDbGroupBean condition) throws Exception {
        try {
            ShardingDbGroupExample example = new ShardingDbGroupExample();
            if (condition != null) {
                ShardingDbGroupExample.Criteria criteria = example.createCriteria();
                if (condition.getId() != null) {
                    criteria.andIdEqualTo(condition.getId());
                }


            }

            return shardingDbGroupMapper.countByExample(example);
        } catch (Exception exp) {
            logger.error(exp.getMessage(), exp);
            throw exp;
        }
    }

    @Transactional(rollbackFor = {RuntimeException.class})
    public boolean updateShardingDbGroup(ShardingDbGroupBean shardingDbGroupBean) throws Exception {
        if (shardingDbGroupBean == null || shardingDbGroupBean.getId() <= 0) {
            return false;
        }
        try {
            shardingDbGroupBean.setUpdateTime(new Date());
            ShardingDbGroup updateBean = BeanUtil.toBean(ShardingDbGroup.class, BeanUtil.toMap(shardingDbGroupBean));
            int updateNum = shardingDbGroupMapper.updateByPrimaryKeySelective(updateBean);
            return updateNum == 1;
        } catch (Exception exp) {
            logger.error(exp.getMessage(), exp);
            throw exp;
        }
    }

    public ShardingDbGroupBean selectShardingDbGroupById(Integer id) throws Exception {
        if (id <= 0) {
            return null;
        }
        try {
            ShardingDbGroup shardingDbGroup = shardingDbGroupMapper.selectByPrimaryKey(id);
            if (shardingDbGroup == null) {
                logger.warn("not found data, tid:{}", id);
                return null;
            }
            return BeanUtil.toBean(ShardingDbGroupBean.class, BeanUtil.toMap(shardingDbGroup));
        } catch (Exception exp) {
            logger.error(exp.getMessage(), exp);
            throw exp;
        }
    }

    public Integer saveShardingDbGroup(ShardingDbGroupBean shardingDbGroupBean) throws Exception {
        if (shardingDbGroupBean == null) {
            return -1;
        }
        try {
            shardingDbGroupBean.setCreateTime(new Date());
            shardingDbGroupBean.setUpdateTime(new Date());
            ShardingDbGroup insertBean = BeanUtil.toBean(ShardingDbGroup.class, BeanUtil.toMap(shardingDbGroupBean));
            shardingDbGroupMapper.insertSelective(insertBean);
            return insertBean.getId();
        } catch (Exception exp) {
            logger.error(exp.getMessage(), exp);
            throw exp;
        }
    }
}
